package org.eiahe.hr.attendance.task;

import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.eiahe.hr.attendance.service.IAnnualLeaveService;
import org.eiahe.hr.attendance.service.IAttendanceAlertService;
import org.eiahe.hr.attendance.service.IAttendanceRecordService;
import org.eiahe.hr.attendance.service.IDingTalkSyncService;
import org.eiahe.hr.attendance.service.IMonthlyAttendanceStatService;
import org.eiahe.hr.attendance.service.IMonthlyOvertimeStatService;
import org.eiahe.hr.attendance.service.ISpecialAttendanceRuleService;
import org.springframework.scheduling.annotation.Scheduled;
import org.springframework.stereotype.Component;

import java.time.LocalDate;

/**
 * 考勤定时任务
 *
 * @author zhangnn
 */
@Slf4j
@RequiredArgsConstructor
@Component
public class SpecialRuleTask {

    private final ISpecialAttendanceRuleService specialAttendanceRuleService;
    private final IDingTalkSyncService dingTalkSyncService;
    private final IAnnualLeaveService annualLeaveService;
    private final IAttendanceRecordService attendanceRecordService;
    private final IMonthlyAttendanceStatService monthlyAttendanceStatService;
    private final IMonthlyOvertimeStatService monthlyOvertimeStatService;
    private final IAttendanceAlertService attendanceAlertService;

    /**
     * 到期提醒定时任务
     * 每天凌晨1点执行
     */
    @Scheduled(cron = "0 0 1 * * ?")
    public void remindExpiring() {
        log.info("开始执行特殊考勤规则到期提醒任务");
        try {
            // 提前7天提醒
            specialAttendanceRuleService.remindExpiring(7);
            log.info("特殊考勤规则到期提醒任务执行完成");
        } catch (Exception e) {
            log.error("特殊考勤规则到期提醒任务执行失败", e);
        }
    }

    /**
     * 钉钉考勤数据同步定时任务
     * 每小时的第5分钟执行
     */
    @Scheduled(cron = "0 5 * * * ?")
    public void syncDingTalkAttendance() {
        log.info("开始自动同步钉钉考勤数据");
        try {
            dingTalkSyncService.autoSync();
            log.info("自动同步钉钉考勤数据完成");
        } catch (Exception e) {
            log.error("自动同步钉钉考勤数据失败", e);
        }
    }

    /**
     * OA请假数据同步定时任务
     * 每天的09:00和15:00执行(每日自动同步2次)
     */
    @Scheduled(cron = "0 0 9,15 * * ?")
    public void syncOaLeave() {
        log.info("开始自动同步OA请假数据");
        try {
            dingTalkSyncService.autoLeaveSync();
            log.info("自动同步OA请假数据完成");
        } catch (Exception e) {
            log.error("自动同步OA请假数据失败", e);
        }
    }

    /**
     * 年假核算定时任务
     * 每年1月1日凌晨2点执行
     */
    @Scheduled(cron = "0 0 2 1 1 ?")
    public void calculateAnnualLeave() {
        log.info("开始执行年度年假核算任务");
        try {
            int year = LocalDate.now().getYear();
            annualLeaveService.calculateAnnualLeaveForYear(year);
            log.info("年度年假核算任务执行完成,年份：{}", year);
        } catch (Exception e) {
            log.error("年度年假核算任务执行失败", e);
        }
    }

    /**
     * 重复打卡合并定时任务
     * 每天1小时执行一次
     */
    @Scheduled(cron = "0 0 * * * ?")
    public void mergeDuplicateClockRecords() {
        log.info("开始执行重复打卡合并任务");
        try {
            // 合并今天的重复打卡记录
            LocalDate today = LocalDate.now();
            Integer mergedCount = attendanceRecordService.mergeDuplicateClockRecords(today);
            log.info("重复打卡合并任务执行完成,合并记录数：{}", mergedCount);
        } catch (Exception e) {
            log.error("重复打卡合并任务执行失败", e);
        }
    }

    /**
     * 月度考勤统计生成任务
     * 每月1日凌晨3点执行
     */
    @Scheduled(cron = "0 0 3 1 * ?")
    public void generateMonthlyAttendanceStats() {
        log.info("开始执行月度考勤统计任务");
        try {
            LocalDate now = LocalDate.now();
            // 统计上个月的数据
            LocalDate lastMonth = now.minusMonths(1);
            int year = lastMonth.getYear();
            int month = lastMonth.getMonthValue();

            monthlyAttendanceStatService.generateMonthlyStats(year, month);
            log.info("月度考勤统计任务执行完成,统计月份：{}年{}月", year, month);
        } catch (Exception e) {
            log.error("月度考勤统计任务执行失败", e);
        }
    }

    /**
     * 月度加班统计生成任务
     * 每月1日凌晨4点执行
     */
    @Scheduled(cron = "0 0 4 1 * ?")
    public void generateMonthlyOvertimeStats() {
        log.info("开始执行月度加班统计任务");
        try {
            LocalDate now = LocalDate.now();
            // 统计上个月的数据
            LocalDate lastMonth = now.minusMonths(1);
            int year = lastMonth.getYear();
            int month = lastMonth.getMonthValue();

            monthlyOvertimeStatService.generateMonthlyStats(year, month);
            log.info("月度加班统计任务执行完成,统计月份：{}年{}月", year, month);
        } catch (Exception e) {
            log.error("月度加班统计任务执行失败", e);
        }
    }

    /**
     * 每日考勤异常提醒生成任务
     * 每天凌晨5点执行
     */
    @Scheduled(cron = "0 0 5 * * ?")
    public void generateDailyAttendanceAlerts() {
        log.info("开始执行每日考勤异常提醒生成任务");
        try {
            LocalDate yesterday = LocalDate.now().minusDays(1);
            attendanceAlertService.generateAlerts(yesterday);
            log.info("每日考勤异常提醒生成任务执行完成,日期：{}", yesterday);
        } catch (Exception e) {
            log.error("每日考勤异常提醒生成任务执行失败", e);
        }
    }

    /**
     * 月度异常汇总邮件发送任务
     * 每月1日凌晨6点执行
     */
    @Scheduled(cron = "0 0 6 1 * ?")
    public void sendMonthlyAlertSummary() {
        log.info("开始执行月度异常汇总邮件发送任务");
        try {
            LocalDate now = LocalDate.now();
            // 发送上个月的汇总
            LocalDate lastMonth = now.minusMonths(1);
            int year = lastMonth.getYear();
            int month = lastMonth.getMonthValue();

            attendanceAlertService.sendMonthlyAlertSummary(year, month);
            log.info("月度异常汇总邮件发送任务执行完成,月份：{}年{}月", year, month);
        } catch (Exception e) {
            log.error("月度异常汇总邮件发送任务执行失败", e);
        }
    }
}
